package tools;

import java.io.Serializable;
import java.util.ArrayList;

public class GameState implements Serializable 
{
	/**
	 * 
	 */
	private static final long serialVersionUID = 4112208751094189439L;
	public ArrayList<Player> players;
	ArrayList<Player> winners = new ArrayList<Player>();
	GameStates state;
	private int numberOfRound;
	private int pot;	
	
	/* ID gracza posiadajacego Dealer Button w biezacej rogrywce, na wypadek gdbyby wyszedl i nie mozna bylo ustalic nastepnego
	 * gracza
	 *  */
	private int dealerButtonPlayerID;
	/* ID gracza bedacego na Small Bind */
	private int smallBlindPlayerID;
	/* ID gracza bedacego na Big Blind */
	private int bigBlindPlayerID;
	/* ID gracza wykonujacego ruch */
	private int turningPlayerID;
	/* ID gracza ktory przebil stawke w biezacej rundzie */
	private int highestBetInRoundPlayerID;
	/* najwyzsza stawka w rundzie licytacji */
	private int highestBetInRound;
	
	public GameState(int numberOfPlayers, int chipsSmallBlind, int chipsBigBlind, int chips)
	{
		this.players = new ArrayList<Player>(numberOfPlayers);
		/* pusty slot aby zajac indeks 0 */
		this.players.add(0, new Player(0, chipsSmallBlind, chipsBigBlind, chips));
		
		for(int i=1; i<=numberOfPlayers; i++)
			this.players.add(i, new Player(i, chipsSmallBlind, chipsBigBlind, chips));
		
		setWaiting();
	}

	public void startGame()
	{
		this.setPot(0);
	}
	
	public void startRounds()
	{
		this.state = GameStates.BETTING_ROUND;
		this.setNumberOfRound(1);
		this.setPot(0);
		this.clearWinners();
	}
	
	public void clearWinners()
	{
		this.winners.clear();
	}
	
	public void addWinner(Player p)
	{
		this.winners.add(p);
	}
	
	public boolean isWinner(Player p)
	{
		return this.winners.contains(p);
	}
	
	public boolean isDraw()
	{
		return (this.winners.size() > 1);
	}
	
	public int getNumberOfRound()
	{
		return numberOfRound;
	}

	public void setNumberOfRound(int numberOfRound)
	{
		this.numberOfRound = numberOfRound;
	}

	public void setPot(int pot)
	{
		this.pot = pot;
	}
		
	public void setTurningPlayer(int n)
	{
		this.turningPlayerID = n;
	}
	
	public int getTurningPlayer()
	{
		return this.turningPlayerID;
	}
	
	public Player addPlayer(int id)
	{
		Player p = getPlayer(id);
		p.setWaiting();
		p.setNewChips();
		return p;
	}
	
	public void removePlayer(int id)
	{
		Player p = getPlayer(id);
		p.setEmptySlot();
	}
	
	public int getPot()
	{
		return this.pot;
	}
	
	public String getState()
	{
		StringBuilder s = new StringBuilder();
		
		if (this.isBettingRound())
		{
			s.append("Betting round: " + this.numberOfRound);
		}
		
		if (this.isExchangeRound())
		{
			s.append("Exchange cards round: " + this.numberOfRound);
		}

		if (this.isFinalRound())
		{
			s.append("Final round. No more exchange cards.");
		}

		if (this.isWaiting())
		{
			s.append("Waiting for players. " + this.countPlayers() + " of " + this.numberOfMaxPlayers() + " are logged in.");
		}

		if (this.isEndGame())
		{
			if (!isDraw())
				s.append("End game. Winner ID is: " + this.getWinnerID());
			else
				s.append("End game. We have a draw. The pot is mine!");
		}
				
		return s.toString();
	}
	
	public Player getWinner()
	{
		Player p=null;
		/* tylko jeden wygrany w tej wersji dlatego kazdy z listy (jeden) bierze cala pule */
		for(Player w: winners)
			return w;
		return p;
	}
	
	public boolean isEndGame()
	{
		return GameStates.END_GAME == this.state;
	}

	public Player getPlayer(int id)
	{
		return (players.get(id));
	}
	
	public void setWaiting()
	{
		this.state = GameStates.WAITING;
		this.pot = 0;
		this.bigBlindPlayerID = 0;
		this.dealerButtonPlayerID = 0;
		this.smallBlindPlayerID = 0;
		this.highestBetInRound = 0;
		this.highestBetInRoundPlayerID = 0;
		this.numberOfRound = 0;
		this.turningPlayerID = 0;
		this.clearWinners();
	}
	
	public boolean isWaiting()
	{
		return GameStates.WAITING == this.state;
	}
	
	public boolean isBettingRound()
	{
		return GameStates.BETTING_ROUND == this.state;
	}

	public boolean isExchangeRound()
	{
		return GameStates.EXCHANGE_ROUND == this.state;
	}

	public boolean isFinalRound()
	{
		return GameStates.FINAL_ROUND == this.state;
	}

	public void setBettingRound()
	{
		state = GameStates.BETTING_ROUND;
	}
	
	public void setFinalRound()
	{
		state = GameStates.FINAL_ROUND;
	}
	
	public void setExchangeRound()
	{
		state = GameStates.EXCHANGE_ROUND;
	}
	
	public int countPlayingPlayers()
	{
		int counter=0;
		for(Player p : players)
			if (p.isPlaying()) counter++;
		return counter;
	}

	public int countPlayers()
	{
		int counter=0;
		for(Player p : players)
			if (p.isPlaying() || p.isWaiting() || p.isFold()) counter++;
		return counter;
	}

	public int countWaitingPlayers()
	{
		int counter=0;
		for(Player p : players)
			if (p.isWaiting()) counter++;
		return counter;
	}
	
	public int numberOfMaxPlayers()
	{
		return this.players.size()-1;
	}

	public int getHighestBetInRoundPlayerID()
	{
		return highestBetInRoundPlayerID;
	}

	public void setHighestBetInRoundPlayerID(int highestBetInRoundPlayerID)
	{
		this.highestBetInRoundPlayerID = highestBetInRoundPlayerID;
	}

	public int getDealerButtonPlayerID()
	{
		return dealerButtonPlayerID;
	}

	public void setDealerButtonPlayerID(int dealerButtonPlayerID)
	{
		this.dealerButtonPlayerID = dealerButtonPlayerID;
	}

	public int getSmallBlindPlayerID()
	{
		return smallBlindPlayerID;
	}

	public void setSmallBlindPlayerID(int smallBlindPlayerID)
	{
		this.smallBlindPlayerID = smallBlindPlayerID;
	}

	public int getBigBlindPlayerID()
	{
		return bigBlindPlayerID;
	}

	public void setBigBlindPlayerID(int bigBlindPlayerID)
	{
		this.bigBlindPlayerID = bigBlindPlayerID;
	}

	public int getHighestBetInRound()
	{
		return highestBetInRound;
	}

	public void setHighestBetInRound(int highestBetInRound)
	{
		this.highestBetInRound = highestBetInRound;
	}

	public void setEndGame()
	{
		this.state = GameStates.END_GAME;	
	}

	public void sharePot()
	{
		/* tylko jeden wygrany w tej wersji dlatego kazdy z listy (jeden) bierze cala pule */
		for(Player p: winners)
			p.addToTotalChips(pot);
	}

	public int getWinnerID()
	{
		return this.getWinner().getID();
	}
}
